# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render,render_to_response,HttpResponse,HttpResponseRedirect
from django.contrib import  auth
from django.contrib.auth.decorators import login_required
from gitpub.models import ProjectInfo,ServerInfo,HostInfo,Logs
import json,urllib2,time,os,commands
import salt.client
import MySQLdb
import logs,mymodules
from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger


#### Configuration ####
DbPort = 3306
DbHost = '192.168.1.65'
DbUser = 'root'
DbPassWord = '123123'
GitHost = '192.168.1.233'

# Create your views here.
def login_view(request):
    if request.method == 'POST':
        logs.log("request is ok")
        UserName = request.POST['username']
        PassWord = request.POST['password']
        user = auth.authenticate(username=UserName,password=PassWord)
        if user is not None and user.is_active:
            auth.login(request,user)
            logs.log("login success by %s" % user)
            Cont = "User [%s] has login." % user
            Addlog = Logs(
                OptUser= user,
                Content= Cont,
                UpdateTime=mymodules.timestamp()
            )
            Addlog.save()
            return HttpResponseRedirect('/index/')
        else:
            return render(request,'login.html',{'error_msg':"用户名或密码错误"})
    else:
        return render_to_response('login.html')


def logout_view(request):
    auth.logout(request)
    user = request.user
    Cont = "User [%s] has login." % user
    Addlog = Logs(
        OptUser=user,
        Content= Cont,
        UpdateTime=mymodules.timestamp()
    )
    Addlog.save()
    return HttpResponseRedirect('/LoginPage/')


@login_required
def index(request):
    logs.log(request.user)
    Project_list = ProjectInfo.objects.order_by('UpdateTime')[0:5]
    Opts = Logs.objects.order_by('-UpdateTime')[0:5]
    return render_to_response('index.html', {'username':request.user,'ProjectList':Project_list,'Options': Opts})

# 跳转到项目添加页面
@login_required
def proadd(request):
## 判断是否是第一次添加项目，server端是否存在git仓库
    Server_list = ServerInfo.objects.all()
    return render_to_response('add.html', {'username':request.user,'data': Server_list})

# 跳转到项目更新页面
@login_required
def proupdate(request):
    aa = ProjectInfo.objects.all()
    return render_to_response('update.html',{'username':request.user,'list':aa})

# 跳转到操作记录页面
@login_required
def opts(request):
    # 获取git文件列表
    Optslog = Logs.objects.order_by('-UpdateTime')
    PagInator = Paginator(Optslog,10)
    Page = request.GET.get('page')
    try:
        contacts = PagInator.page(Page)
    except PageNotAnInteger:
        contacts = PagInator.page(1)
    except EmptyPage:
        contacts = PagInator.page(PagInator.num_pages)
    return render_to_response('opts.html',{
        'username':request.user,
        # 'optlogs':Optslog,
        # 'lines': Logs.objects.count()
        'contacts': contacts
    })

# 批量命令执行
@login_required
def commands(request):
    ServerList = HostInfo.objects.all()
    return render_to_response('commands.html',{
        'username':request.user,
        'serverlist': ServerList
    })

def saltcmd(request):
    if request.method == 'POST':
        logs.log("function be requested %s " % saltcmd.__name__)
        HostList = eval(request.body)['hostname']
        logs.log(HostList)
        Command = eval(request.body)['command']
        Result = {}
        if HostList:
            Client = salt.client.LocalClient()
            Jid = {}
            logs.log(HostList)
            for host in HostList:
                if len(HostInfo.objects.filter(HostName=host)) > 0:
                    ret = Client.run_job(host, 'cmd.run', [Command])
                    logs.log(ret)
                    Jid[host] = ret['jid']
                else:
                    print host
                    Result[host] = ("Not in host DB",'0')
            if Jid:
                for k,v in Jid.items():
                    SQL = "select `return`,`success` FROM  salt_returns WHERE jid='%s'" % v
                    logs.log("SQL is : "+SQL)
                    logs.log("K is :" + k)
                    logadd = Logs(OptUser=request.user.username,
                                        Content=(
                                            "User [%s] run Command [%s] on Server %s" % (request.user.username, Command, k)),
                                        UpdateTime=mymodules.timestamp())
                    logadd.save()
                    i = 0
                    while i < 5:
                        Db = MySQLdb.connect(DbHost, DbUser, DbPassWord, 'salt')
                        cursor = Db.cursor()
                        try:
                            cursor.execute(SQL)
                            Query = cursor.fetchone()
                        except Exception,e:
                            logs.log(e)
                            Query = ''
                        if Query is not None:
                            Result[k] = Query
                            break
                        else:
                            i += 1
                            logs.log(i)
                            logs.log("query is None")
                            time.sleep(2)
                            continue
                        cursor.close()
                        Db.close()
                    else:
                        Result[k] = "No return"

                return HttpResponse(json.dumps({'resu':"success",'result':Result}))
            else:
                return HttpResponse(json.dumps({'resu':"Error"}))
    else:
        return HttpResponse(json.dumps({'resu':"method must be post"}))


# 添加项目到数据库
@login_required
def Addpro(request):
    if request.method == 'POST':
        print request.POST['Hosts']
        project = ProjectInfo(
            IpAddress = request.POST['Hosts'],
            ProJectName = request.POST['Name'],
            ProPath = request.POST['ProPath'],
            GitAddress = request.POST['GitAddr'],
            GitRepo = request.POST['GitRepo'],
            UserName = request.POST['UserName'],
            PassWord = request.POST['Keys'],
            ConTent = request.POST['ConTent'],
            UpdateTime = mymodules.timestamp()
        )
        project.save()
        logadd = Logs(OptUser=request.user.username,
                      Content = "User 【%s】 Add Project： 【%s】" % (request.user.username, request.POST['Name']),
                      UpdateTime=mymodules.timestamp()
                      )
        logadd.save()
        return HttpResponse("success")

# 项目更新页面
@login_required
def options(request):
    if request.method == 'GET':
        print "Request is GET"
        Id = request.GET['id']
        Data  = ProjectInfo.objects.get(id=Id)
        # gitlab 项目列表
        return render_to_response('option.html',
                                  {
                                      'username':request.user,
                                      'project': Data,
                                      'title': '项目更新'
                                  }
                                  )

#全部更新
@login_required
def AllUpdate(request):
    Result = {}
    if request.method == 'POST':
        Proid = request.POST['proid']
        Project = ProjectInfo.objects.get(id=Proid)
        ProName = Project.ProJectName
        Project_path = Project.ProPath
        Git_addr = Project.GitAddress
        Git_repo = Project.GitRepo
        Host_list = Project.IpAddress.split(';')
        Git_Url = "http://"+Project.UserName+":"+Project.PassWord+"@"+Git_addr+Git_repo
        HostName_list = []
        for m in Host_list:
            try:
                Address = HostInfo.objects.get(ServerIp=m)
            except Exception,e:
                Address = ''
            if Address:
                HostName_list.append(Address.HostName)
        Client = salt.client.LocalClient()
        if HostName_list:
            # 循环执行
            Jid_dict = {}
            for host in HostName_list:
                logs.log("Start update server %s" % host)
                # 判断目标机是否存在文件夹
                Dir_ret = Client.run_job(host,'file.directory_exists',[Project_path])
                Jid = Dir_ret['jid']
                time.sleep(2)
                # 查询数据库执行结果
                Db = MySQLdb.connect(
                    DbHost, DbUser, DbPassWord, "salt"
                )
                cursor = Db.cursor()
                Return_cmd = "SELECT `return`,`success` FROM salt_returns WHERE jid='%s'" % Jid
                cursor.execute(Return_cmd)
                Db_data = cursor.fetchone()
                cursor.close()
                Db.close()
                logs.log(Db_data)
                # 判断执行结果，并执行相应操作
                if Db_data[0] == 'false':
                    # git clone
                    logs.log("%s Start git clone" % host)
                    # 多进程处理 v1.1
                    # 无法通过saltstack api调用更新命令，saltstack无git api，直接使用命令行
                    # 应该这么写 ↓
                    Salt_cmd = "git clone %s %s" % ( Git_Url, Project_path )
                    try:
                        ret = Client.run_job(host,'cmd.run', [Salt_cmd])
                    except Exception, e:
                        Result[host] = e
                    else:
                        Jid_dict[host] = ret['jid']
                elif Db_data[0] == 'true':
                    # git pull
                    logs.log("%s Start git pull" % host)
                    Salt_cmd = "cd %s&& git pull" % Project_path
                    try:
                        ret = Client.run_job(host,'cmd.run', [Salt_cmd])
                    except Exception,e:
                        Result[host] = e
                    else:
                        logs.log(ret['jid'])
                        Jid_dict[host] = ret['jid']
                else:
                    Result[host] = '判断文件夹失败'
                logs.log(Result)
            for k,v in Jid_dict.items():
                logadd = Logs(OptUser= request.user.username,
                              Content = "用户 【%s】 执行全部更新，项目：【%s】" % (request.user.username, ProName),
                              UpdateTime = mymodules.timestamp())
                logadd.save()
                SQL = "SELECT `return`,`success` FROM salt_returns WHERE jid='%s';" % Jid_dict[k]
                logs.log("Query db sql is : %s " % SQL)
                i = 0
                logs.log("Num i before while is : %s" % i)
                while i < 5:
                    Db = MySQLdb.connect(DbHost, DbUser, DbPassWord, 'salt')
                    cursor = Db.cursor()
                    try:
                        a = cursor.execute(SQL)
                        logs.log("Query data result is : %s" % a)
                        Query = cursor.fetchone()
                    except Exception,e:
                        logs.log("Query data error: %s" % e)
                        Query = ''
                    if Query is not None:
                        logs.log(Query)
                        Result[k] = Query
                        ProjectInfo.objects.filter(id=Proid).update(UpdateTime=mymodules.timestamp())
                        break
                    # if len(Result) == len(Jid_dict):
                    #     break
                    else:
                        logs.log("No data exists, sleep 1.")
                        logs.log("Num i is : %s" % i)
                        time.sleep(1)
                        i = i + 1
                        continue
                else:
                    Result[k] = "No Return"
                    cursor.close()
                    Db.close()
        else:
            Result['error'] = "Hostnot exists"
        return HttpResponse(json.dumps(Result))
    else:
        Result["Error"] = "Method error.Not use post"
        return HttpResponse(json.dumps(Result))

# 选中文件更新
@login_required
def FileUpdate(request):
    Result = {}
    if request.method == 'POST':
        ProId = request.POST['Proid']
        logs.log(request.POST['Files'])
        Filenames = request.POST['Files'].split(',')
        logs.log(ProId)
        logs.log(Filenames)
        Project = ProjectInfo.objects.get(id=ProId)
        ProPath = Project.ProPath
        Salt_cmd = "cd %s && git fetch && git checkout origin/master -- %s" % ( ProPath, (' ').join(Filenames))
        logs.log(Salt_cmd)
        HostName_list = []
        Host_list = Project.IpAddress.split(';')
        logs.log(Host_list)
        for m in Host_list:
            try:
                Address = HostInfo.objects.get(ServerIp=m)
            except Exception, e:
                logs.log(e)
                Address = ''
            if Address:
                HostName_list.append(Address.HostName)
        Client = salt.client.LocalClient()
        if HostName_list:
            # 循环执行
            Jid_dict = {}
            logs.log("HostName_list is %s" % HostName_list)
            for host in HostName_list:
                # try:
                logs.log("Start run [cmd.run] module and run salt_cmd in [%s] " % host)
                ret = Client.run_job(host,'cmd.run', [Salt_cmd])
                # except Exception,e:
                # else:
                Jid_dict[host] = ret['jid']
            logs.log(ret)
            logs.log("Start connection MySQL db")

            for k,v in Jid_dict.items():
                SQL = "SELECT `return`,`success` FROM salt_returns WHERE jid='%s';" % Jid_dict[k]
                logs.log("Query db sql is : %s " % SQL)
                i = 0
                logs.log("Num i before while is : %s" % i)
                while i < 5:
                    Db = MySQLdb.connect(DbHost, DbUser, DbPassWord, 'salt')
                    cursor = Db.cursor()
                    try:
                        a = cursor.execute(SQL)
                        logs.log("Query data result is : %s" % a)
                        Query = cursor.fetchone()
                    except Exception,e:
                        logs.log("Query data error: %s" % e)
                        Query = ''
                    if Query is not None:
                        logs.log(Query)
                        Result[k] = Query
                        ProjectInfo.objects.filter(id=ProId).update(UpdateTime=mymodules.timestamp())
                        break
                    # if len(Result) == len(Jid_dict):
                    #     break
                    else:
                        logs.log("No data exists, sleep 1.")
                        time.sleep(1)
                        i = i + 1
                        continue
                    cursor.close()
                    Db.close()
                else:
                    Result[k] = "No Return"
        logadd = Logs(OptUser = request.user.username,Content= ('User [%s] Update file 【%s】' % (request.user.username, Filenames)), UpdateTime=mymodules.timestamp())
        logadd.save()


        logs.log(Result)
        return HttpResponse(json.dumps(Result))
    else:
        Result = {'result': "method error"}
        return  HttpResponse(json.dump(Result))

@login_required
def ProList(request):
    Url = 'http://'+ GitHost +'/api/v3/projects/34/repository/tree?private_token='
    Token = 'hz4FLehi6vFRwQN79ZBu'
    GitUrl = Url + Token
    logs.log(GitUrl)
    req = urllib2.Request(url = Url+Token)
    res = urllib2.urlopen(req)
    ProjectList = res.read()


    return render_to_response('gitlabs.html', json.dumps(ProjectList))

def GetFileList(request):
    if request.method == 'GET':
        Path = request.GET['FilePath']
        ProName = request.GET['repository']
        Url = 'http://'+ GitHost +'/api/v3/projects/'
        Token = 'hz4FLehi6vFRwQN79ZBu'
        # search project and get project id
        SearchUrl = Url + 'all?private_token='+Token+'&search='+ProName
        logs.log(SearchUrl)
        try:
            res = urllib2.Request(SearchUrl)
            req = urllib2.urlopen(res)
            ProjectId = json.loads(req.read())[0]['id']
        except Exception,e:
            logs.log(e)
        GitUrl = Url + str(ProjectId) + '/repository/tree'+'?private_token=' + Token + '&path=' + Path
        logs.log(GitUrl)
        res = urllib2.Request(url = GitUrl)
        req = urllib2.urlopen(res)
        ListDir = req.read()
        logs.log(ListDir)
        logs.log(type(json.dumps(ListDir)))
        return HttpResponse(ListDir)